import express = require("express");
import { Request, Response } from "express";

import PWSApp from "./app";
import Logger from "./logger";
import * as utils from "./utils";
import { IUnknown } from "./types";
import { RouteType } from "./defines";

import Mongo from "./mongo";
import Session = Express.Session;
import { ErrCode } from './error.code';

let RouteTypeNames: string[] = [];
for( let k in RouteType ) {
    if( typeof RouteType[k] === 'number' ) {
        RouteTypeNames.push( k.toLowerCase() );
    }
}

export class BaseAction implements IUnknown {
    private _app: PWSApp;
    private _root: string           = '/';
    private _router: express.Router = express.Router();

    constructor( app: PWSApp ) {
        this._app = app;
        if( !app ) {
            throw new Error( 'app must be an instance of PWSApp!' );
        }
        this._setRoutes();
        this._registerRoutes();
    }

    get app(): PWSApp {
        return this._app;
    }

    get db(): Mongo {
        return this.app.db;
    }

    get root(): string {
        return this._root;
    }

    get logger(): Logger {
        return this._app.logger;
    }

    name(): string {
        return 'BaseAction';
    }

    toString(): string {
        return this.name();
    }

    protected _setRoot( root: string ): void {
        this._root = root;
    }

    protected _registerRoutes(): void {
        this._app.registerRoutes( this._root, this._router );
    }

    protected _route( type: RouteType, path: string | RegExp, func: express.RequestHandler ): void {
        this._router[RouteTypeNames[type]]( path, func.bind( this ) );
    }

    protected _setRoutes(): void {
    }

    protected _errHandler( req: Request, res: Response, err: any ): void {
        let regHtml = /(application\/json|text\/plain)/;
        if( utils.isError( err ) ) {
            this.logger.E( this.name(), `${err.msg || ''}\n${err.stack}` );
        }

        if( req.xhr || regHtml.test( req.headers['accept'] ) ) {
            res.send( err );
            return;
        }
        if(err && err.err && err.msg){
            res.render( 'common/error.html', err );
            return;
        }

        let result;
        switch(err.err_code){
            case ErrCode.ResNotFound:
            case ErrCode.ProdNotFound:
                result = {
                    msg: '资源未找到',
                    err: { code: 404, msg: '你访问的资源未找到，请检查输入是否有效!' }
                };
                break;
            case ErrCode.OrderStatusErr:
                result = {
                    msg: '请求已接受',
                    err: { code: 202, msg: '请求已提交，订单状态不正确!' }
                };
                break;
            default:
                result = {
                    msg: '服务器内部错误',
                    err: { code: 500, msg: '非常抱歉,请稍后重试或者联系管理员!' }
                };
        }
        res.render( 'common/error', result );
    }
}
